'''
Created on Apr 26, 2011

@author: All

Put some helper function in this file 
'''

import base64, datetime, hashlib, json, string, time
from common import framework, server_log
from common.server_exception import TokenInvalidError
from includes import web
from common.config import SERVER_KEY

CLIENT_TYPE_ID = {
                  'iPad': 1,
                  'iPhone': 2,
                  'iPod touch': 3,
                  'iPhone Simulator': 4,                   
                  'Android': 11,
                  'Web Client': 12,
                  'Unknown': 100
                  }

def utc_now():
    return datetime.datetime.utcnow().replace(microsecond=0)

def in_clause(id_list):
    try:
        for i in id_list:
            if type(i) not in (int, long):
                return ''
        return str(set(id_list))[5:-2].translate(None,'L')
    except Exception:
        server_log.warning()
        return ''

def _decode_list(lst):
    newlist = []
    for i in lst:
        if isinstance(i, unicode):
            i = i.encode('utf-8')
        elif isinstance(i, list):
            i = _decode_list(i)
        newlist.append(i)
    return newlist

def _decode_dict(dct):
    newdict = {}
    for k, v in dct.iteritems():
        if isinstance(k, unicode):
            k = k.encode('utf-8')
        if isinstance(v, unicode):
            v = v.encode('utf-8')
        elif isinstance(v, list):
            v = _decode_list(v)
        newdict[k] = v
    return newdict

def json_load_to_str(s):
    return json.loads(s, object_hook=_decode_dict)

def base64_url_decode(inp):
    padding_factor = (4 - len(inp) % 4) % 4
    inp += "="*padding_factor
    return base64.b64decode(unicode(inp).translate(dict(zip(map(ord, u'-_'), u'+/'))))

def sha1_encryption(input, str_flag = False):
    try:        
        if (str_flag == False):
            dig = hashlib.sha1(input).digest()
        else:
            dig = hashlib.sha1(input).hexdigest()
        return dig
    except Exception:
        return None

def get_client_info():
    sdk = framework.get_android_sdk_version()
    device_model = framework.get_device_model()
    client_version = framework.get_client_version()
    device_type_id = 100
        
    if ((sdk is not None) and ((str(sdk).startswith('android')) == True)):
        device_type_id = 11    
        
    if (CLIENT_TYPE_ID.has_key(device_model)):
        device_type_id = CLIENT_TYPE_ID[device_model]
    
    result = {}
    result['device_type_id'] = device_type_id  
    result['client_version'] = client_version
    
    return result

# liliu: calculate age from the birthday
def calculate_age(birthday_info, is_string = False):   
    """
    take a birthday e.g. 05/04/2011
    return the age (int)
    """
    
    if (is_string):
        time_format = "%m/%d/%Y"
        birthday = datetime.datetime.strptime(birthday_info, time_format)
    else:
        birthday = birthday_info
    now = utc_now()
    age = now.year - birthday.year 
    if now.month < birthday.month :
        age -= 1
    elif (now.month == birthday.month and now.day < birthday.day):
        age -= 1    
    return age


# time convert function, created by qi, Nov-2012
# parameter: ts_to_dt, 
#            True  - convert from timestamp to datetime  
#            False - convert from datetime to timestamp
#            None  - convert direction is decided by date_param parameter type 
def date_format(date_param, ts_to_dt = None):
    if not date_param:
        return None
    if ts_to_dt is None:
        if type(date_param) in (float, int, long):
            return datetime.datetime.utcfromtimestamp(int(date_param))
        elif type(date_param) is datetime.datetime:
            return time.mktime(date_param.timetuple()) - time.timezone
    if ts_to_dt:
        return datetime.datetime.utcfromtimestamp(int(date_param))
    else:
        return time.mktime(date_param.timetuple()) - time.timezone


def str_to_date(date_str):
    if type(date_str) is str or type(date_str) is unicode:
        if date_str == "/Date(0)/":
            return None
        
        iphone_tz = long(framework.get_http_secondsfromgmt() or web.cookies().get('SECONDSFROMGMT', '0'))
        target_tz = None

        if target_tz is None:
            target_tz = iphone_tz
        
        begin_idx = date_str.index('(') + 1
        end_idx = date_str.index(')')
        timestamp = string.atoi(date_str[begin_idx:end_idx]) / 1000.0
        
        timestamp += iphone_tz - target_tz
        
        date1 = datetime.datetime.utcfromtimestamp(timestamp)
#        if (tzinfo != 0):
#            date1 = date1 + datetime.timedelta(hours = tzinfo)
        return date1
    elif type(date_str) is datetime.datetime:
        return date_str
    else:
        return None

## change datetime.datetime format into "\/Date(1234567890)\/" string
def date_to_str(date_time):
    try:
        iphone_tz = long(framework.get_http_secondsfromgmt() or web.cookies().get('SECONDSFROMGMT', '0'))
    except Exception:
        iphone_tz = 0

    target_tz = None

    if target_tz is None:
        target_tz = iphone_tz
    
    if type(date_time) is datetime.datetime:
        date_time = date_time - datetime.timedelta(seconds = iphone_tz - target_tz)
        timestamp = (time.mktime(date_time.timetuple()) - time.timezone) * 1000

        return "/Date(%d)/" % timestamp
    elif type(date_time) is str or type(date_time) is unicode:
        return date_time
    else:
        return None
    
# get emma_id and device_id from header 'ALERT'
def get_id_from_header(user_id_only_flag = True):
    auth_token = framework.get_server_key()
    if not auth_token:
        raise TokenInvalidError('No token available')
    user_id = auth_token.split('|')[0]
    if (user_id_only_flag == True):
        return long(user_id)
     
    device_id = auth_token.split('|')[1]
    return (long(user_id), device_id)    

def md5_encryption(*args):
    try:
        input = ''.join([str(i) if i is not None else '' for i in args])
        input += SERVER_KEY
        md5 = hashlib.md5()
        md5.update(input) 
        return md5.hexdigest()
    except Exception:
        server_log.warning()
        return None

